Exemplary embodiments of the present invention relate to object-oriented software development, and more particularly, to class hierarchies of object-oriented applications.
During the design of a complex software system, it can be essential to decompose the system into smaller and smaller parts, each of which may then be refined independently. Object-oriented analysis and design, which directly reflects the topology of high-order, object-oriented programming languages such as Smalltalk, Object PASCAL programming language, C++, the Common Lisp Object System (CLOS), Eiffel, Visual C#, and JAVA programming languages, leads to an object-oriented decomposition. The underlying concept of object-oriented analysis is that one should model software systems as collections of cooperating objects, treating individual objects as instances of a class within a hierarchy of classes. A class is a set of objects that share a common structure, common behavior, and common semantics. Thus, the class hierarchies within a complex system, which provides a ranking or ordering of the abstractions within a design, highlight the common behavior and structure within the system.
Object-oriented programming can thus be defined as a method of implementation in which programs are organized as cooperative collections of objects, each of which represents an instance of some class, and whose classes are all members of a hierarchy of classes united through inheritance relationships. Inheritance is an essential element of object-oriented systems. Essentially, inheritance defines a relationship among classes, wherein one class shares the structure or behavior defined in one or more classes (respectively denoting single inheritance and multiple inheritance). Inheritance thus represents a hierarchy of abstractions in which a subclass inherits from one or more superclasses. Typically, a subclass augments or redefines the existing structure and behavior of its superclasses by specializing the more general structure or behavior of its superclasses.
As a software system developed using an object-oriented programming language evolves over time, it is often desirable to modify the existing classes, as well to add new classes. Some of these new classes may inherit from existing classes, while some may form new hierarchies of classes. In practice, when adding a new class to an existing object-oriented design, a developer will often not define the new class from scratch but rather locate a similar, already existing class, copy it, and then alter it as desired (for example, by adding and/or removing data members). As an example, the following class hierarchy taken from a hardware world can be considered (where ‘A→B’ is used to represent a relationship in which class A inherits from class B): NiceBridge→IOBridge″BasicBridge→HardwareComponent. If a developer seeks to add a new class, GoodBridge, that is similar to class NiceBridge and inherits from class BasicBridge, the developer may decide to implement the class by performing the following actions manually: (1) Create an identical copy of class IOBridge and name it class GoodBridge; (2) inspect the deltas between class NiceBridge and class IOBridge; and (3) apply the deltas to class GoodBridge.
In the above example, where the classes contain only a few attributes and data members, and where the inherited class is a close ancestor to the newly implemented class, performing the manual operations listed above can be a fairly simple task for the developer. In industrial-strength software systems (for example, data systems that maintain the integrity of hundreds or thousands of records of information while allowing concurrent updates and queries and systems for the command and control of real-world entities such as the routing of air or railway traffic) in which applications can be implemented with a very rich set of behaviors, class hierarchies with many levels, and classes with many attributes and data members, however, this task can be rather tedious and error-prone, particularly where the inherited class is several levels above the similar class. Industrial-strength software systems tend to have a long-lifespan, and applications in such systems are the means and artifacts of incremental and exploratory development. It can therefore be exceedingly difficult, if not impossible, for a developer to comprehend all the subtleties of the design of an industrial-strength software system.